package com.ymt.bpm.dao;

import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import com.ymt.bpm.appboot.MybatisConfiguration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;

@Repository
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(MybatisConfiguration.class)
public class MDao extends SqlSessionDaoSupport {

	private Logger logger = Logger.getLogger(MDao.class.getName());

	@Value("${mybatis.custom-common-dao-prefix}")
	private String customCommonDaoPrefix;

	// 从spring注入原有的sqlSessionTemplate
	private SqlSessionTemplate sqlSessionTemplate;

	@Override
	@Autowired
    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        super.setSqlSessionTemplate(sqlSessionTemplate);
    }

	private String fullSqlId(String mapper, String sqlid) {
		return fullSqlId(customCommonDaoPrefix, mapper, sqlid);
	}

	private String fullSqlId(String nameSpacePrefix, String mapper, String sqlid) {
		return nameSpacePrefix+"."+mapper+"."+sqlid;
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> selectAllList(String mapper, String sqlid) {
		return (List<T>) this.getSqlSession().selectList(fullSqlId(mapper, sqlid));
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> selectList(String mapper, String sqlid, Map<String, Object> paramObj) {
		return (List<T>) this.getSqlSession().selectList(fullSqlId(mapper, sqlid), paramObj);
	}

	public <T> List<T> selectListByObj(String mapper, String sqlid, T paramObj) {
		return (List<T>) this.getSqlSession().selectList(fullSqlId(mapper, sqlid), paramObj);
	}

	public <T> List<T> selectObjListByObj(String mapper, String sqlid, Object paramObj) {
		return (List<T>) this.getSqlSession().selectList(fullSqlId(mapper, sqlid), paramObj);
	}

	@SuppressWarnings("unchecked")
	public <T> List<T> selectList(String mapper, String sqlid, Map<String, Object> paramObj, RowBounds arg3) {
		return (List<T>) this.getSqlSession().selectList(fullSqlId(mapper, sqlid), paramObj, arg3);
	}

	@SuppressWarnings("unchecked")
	public <T> T selectOne(String mapper, String sqlid, Object primaryKey) {
		return (T) this.getSqlSession().selectOne(fullSqlId(mapper, sqlid), primaryKey);
	}

	@SuppressWarnings("unchecked")
	public <T> T selectOne(String mapper, String sqlid, Map<String, Object> paramObj) {
		return (T) this.getSqlSession().selectOne(fullSqlId(mapper, sqlid), paramObj);
	}

	public <T> T selectOneByObject(String mapper, String sqlid, T paramObj) {
		return (T) this.getSqlSession().selectOne(fullSqlId(mapper, sqlid), paramObj);
	}

	@SuppressWarnings({ "rawtypes" })
	public Map selectMap(String mapper, String sqlid, Object paramObj, String mapKey) {
		return this.getSqlSession().selectMap(fullSqlId(mapper, sqlid), paramObj, mapKey);
	}

	@SuppressWarnings({ "rawtypes" })
	public Map selectMap(String mapper, String sqlid, Map<String, Object> arg1, String arg2) {
		return this.getSqlSession().selectMap(fullSqlId(mapper, sqlid), arg1, arg2);
	}

	@SuppressWarnings({ "rawtypes" })
	public Map selectMap(String mapper, String sqlid, Map<String, Object> arg1, String arg2, RowBounds arg3) {
		return this.getSqlSession().selectMap(fullSqlId(mapper, sqlid), arg1, arg2, arg3);
	}

	public int delete(String mapper, String sqlid, Object paramObj) {
		return this.getSqlSession().delete(fullSqlId(mapper, sqlid), paramObj);
	}

	public int delete(String mapper, String sqlid, Map<String, Object> paramObj) {
		return this.getSqlSession().delete(fullSqlId(mapper, sqlid), paramObj);
	}

	public int insert(String mapper, String sqlid, Map<String, Object> paramObj) {
		return this.getSqlSession().insert(fullSqlId(mapper, sqlid), paramObj);
	}

	public int insert(String mapper, String sqlid) {
		return this.getSqlSession().insert(fullSqlId(mapper, sqlid));
	}

	public <T> int insert(String mapper, String sqlid, T paramObj) {
		return this.getSqlSession().insert(fullSqlId(mapper, sqlid), paramObj);
	}

	public void select(String mapper, String sqlid, ResultHandler arg1) {
		this.getSqlSession().select(fullSqlId(mapper, sqlid), arg1);
	}

	public void select(String mapper, String sqlid, Map<String, Object> paramObj, ResultHandler arg1) {
		this.getSqlSession().select(fullSqlId(mapper, sqlid), paramObj, arg1);
	}

	public void select(String mapper, String sqlid, Map<String, Object> paramObj, RowBounds arg3,
						ResultHandler arg1) {
		this.getSqlSession().select(fullSqlId(mapper, sqlid), paramObj, arg3, arg1);
	}

	public int update(String mapper, String sqlid, Map<String, Object> paramObj) {
		return this.getSqlSession().update(fullSqlId(mapper, sqlid), paramObj);
	}

	public <T> int update(String mapper, String sqlid, T paramObj) {
		return this.getSqlSession().update(fullSqlId(mapper, sqlid), paramObj);
	}

	/**
	 * 批量更新 方法描述：批量更新（效率没有在配置文件上的高）
	 * 
	 * @param statementName
	 * @param list
	 * @throws DataAccessException
	 * @author anps
	 * @date 2013-4-3 上午11:14:37
	 * @comment
	 */
	public <T> int batchUpdate(String mapper, final String statementName, List<T> list)
			throws DataAccessException {

		SqlSession session = ((SqlSessionTemplate)this.getSqlSession()).getSqlSessionFactory()
				.openSession(ExecutorType.BATCH, false);
		int count = 0;
		try {
			if (null != list && list.size() > 0) {
				logger.finer("batchUpdate size = " + list.size());
				int size = 10000;

				for (int i = 0, n = list.size(); i < n; i++) {
					count += this.update(mapper, statementName, list.get(i));
					if (i % 1000 == 0 || i == size - 1) {
						// 手动每1000个一提交，提交后无法回滚
						session.commit();
						// 清理缓存，防止溢出
						session.clearCache();
					}
				}
			}
			return count;
		} /*
		 * catch (Exception e){ session.rollback(); e.printStackTrace();
		 * logger.severe("batchUpdate error: id [" + statementName +
		 * "], parameterObject [" + list + "].  Cause: " + e.getMessage()); }
		 */finally {
			session.close();
		}
	}

	/**
	 * 批量插入 方法描述：批量插入（效率没有在配置文件上的高）
	 * 
	 * @param statementName
	 * @param list
	 * @throws DataAccessException
	 * @author anps
	 * @date 2013-4-3 上午11:27:39
	 * @comment
	 */
	public <T> int batchInsert(String mapper, String statementName, List<T> list)
			throws DataAccessException {

		SqlSession session = ((SqlSessionTemplate)this.getSqlSession()).getSqlSessionFactory()
				.openSession(ExecutorType.BATCH, false);
		int count = 0;
		int size = 10000;
		try {
			if (null != list && list.size() > 0) {
				logger.finer("batchInsert size = " + list.size());

				for (int i = 0, n = list.size(); i < n; i++) {
					count += this.insert(mapper, statementName, list.get(i));
					if (i % 1000 == 0 || i == size - 1) {
						// 手动每1000个一提交，提交后无法回滚
						session.commit();
						// 清理缓存，防止溢出
						session.clearCache();
					}
				}
			}
			return count;
		} /*
		 * catch (Exception e){ session.rollback(); e.printStackTrace();
		 * logger.severe("batchInsert error: id [" + statementName +
		 * "], parameterObject [" + list + "].  Cause: " + e.getMessage()); }
		 */finally {
			session.close();
		}
	}

	/**
	 * 批量删除 方法描述：批量删除（效率没有在配置文件上的高）
	 * 
	 * @param statementName
	 * @param list
	 * @throws DataAccessException
	 * @author anps
	 * @date 2013-4-3 上午11:29:53
	 * @comment
	 */
	public int batchDelete(String mapper, String statementName, List<Map<String, Object>> list)
			throws DataAccessException {
		SqlSession session = ((SqlSessionTemplate)this.getSqlSession()).getSqlSessionFactory()
				.openSession(ExecutorType.BATCH, false);
		int count = 0;
		int size = 10000;
		try {
			if (null != list && list.size() > 0) {
				logger.finer("batchDelete size = " + list.size());

				for (int i = 0, n = list.size(); i < n; i++) {
					count += this.delete(mapper, statementName, list.get(i));
					if (i % 1000 == 0 || i == size - 1) {
						// 手动每1000个一提交，提交后无法回滚
						session.commit();
						// 清理缓存，防止溢出
						session.clearCache();
					}
				}
			}
			return count;
		} /*
		 * catch (Exception e){ session.rollback(); e.printStackTrace();
		 * logger.severe("batchDelete error: id [" + statementName +
		 * "], parameterObject [" + list + "].  Cause: " + e.getMessage()); }
		 */finally {
			session.close();
		}
	}

}
